#include "OpenGLDriver.h"
#include "../../Config.h"
#include "../../include/I3DCameraSceneNode.h"
#include "../../ReadedFont.h"
#include "OpenGLTexture.h"

#ifdef _MSC_VER
#pragma comment(lib, "OpenGL32.lib")
#pragma comment(lib, "glu32.lib")
#endif
#ifdef __COMPILE_WIN32__
#include <windows.h>
#endif
#include <GL/gl.h>
#include <GL/glu.h>

#include <math.h>
#include "../../include/PowerLibraryEngine.h"

COpenGLDriver::COpenGLDriver(StartDriverParams *DrvParams):CNullDriver(DrvParams)
{
	if (DrvParams)
	{
		UseVertexArray = DrvParams->UseVertexArray;
	}
	else
	{
		UseVertexArray = true;
	}
}

COpenGLDriver::~COpenGLDriver()
{
}

void COpenGLDriver::InitDriver()
{
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_NORMALIZE);
	/*
	#ifdef __LIGHTING__
	glClearDepth(1.0);
	glEnable(GL_LIGHTING);
	glEnable(GL_COLOR_MATERIAL);
	#endif
	*/
	glClearDepth(1.0f);			// Profundidad del buffer de profundidad. Hace que lo que esta
	glDepthFunc(GL_LEQUAL);		// Comparacion del buffer de profundidad.
	glEnable(GL_DEPTH_TEST);	// Habilita test de profundidad. A partir de ahora, lo que
	glShadeModel(GL_SMOOTH);    // Renderizado suave. Cuanta mejor calidad mas lento. Nosotros
	glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);   // Calidad buena de perspectiva.

	glEnable(GL_LIGHTING);
	// Encendemos la luz 0.
	glEnable(GL_LIGHT0);

	BackColor.SetRGBA(0.0,0.0,0.0,0.0);
}

void COpenGLDriver::BeginRender()
{
	CNullDriver::BeginRender();

	ClearBuffers(true,true,true,BackColor);
	SceneManager->GetDrawableFaceManager()->ClearRenderList();
}

void GetMatrix(vPos *a)
{
	glGetFloatv(GL_MODELVIEW_MATRIX,a);
}
void GetMatrixp(vPos *a)
{
	glGetFloatv(GL_PROJECTION_MATRIX,a);
}
/*
#define CACHE_SIZE	240
struct GLUquadric {
	GLint	normals;
	GLboolean	textureCoords;
	GLint	orientation;
	GLint	drawStyle;
//	void	(GLAPIENTRY *errorCallback)( GLint );
};
#define COS cos
#define SIN sin
#define SQRT sqrt

void gluSphere2(GLUquadric *qobj, GLdouble radius, GLint slices, GLint stacks)
{
	GLint i,j;
	GLfloat sinCache1a[CACHE_SIZE];
	GLfloat cosCache1a[CACHE_SIZE];
	GLfloat sinCache2a[CACHE_SIZE];
	GLfloat cosCache2a[CACHE_SIZE];
	GLfloat sinCache3a[CACHE_SIZE];
	GLfloat cosCache3a[CACHE_SIZE];
	GLfloat sinCache1b[CACHE_SIZE];
	GLfloat cosCache1b[CACHE_SIZE];
	GLfloat sinCache2b[CACHE_SIZE];
	GLfloat cosCache2b[CACHE_SIZE];
	GLfloat sinCache3b[CACHE_SIZE];
	GLfloat cosCache3b[CACHE_SIZE];
	GLfloat angle;
	GLfloat zLow, zHigh;
	GLfloat sintemp1 = 0.0, sintemp2 = 0.0, sintemp3 = 0.0, sintemp4 = 0.0;
	GLfloat costemp1 = 0.0, costemp2 = 0.0, costemp3 = 0.0, costemp4 = 0.0;
	GLboolean needCache2, needCache3;
	GLint start, finish;

	if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
	if (stacks >= CACHE_SIZE) stacks = CACHE_SIZE-1;
	if (slices < 2 || stacks < 1 || radius < 0.0) {
//		gluQuadricError(qobj, GLU_INVALID_VALUE);
		return;
	}

	needCache2 = needCache3 = GL_FALSE;

	if (qobj->normals == GLU_SMOOTH) {
		needCache2 = GL_TRUE;
	}

	if (qobj->normals == GLU_FLAT) {
		if (qobj->drawStyle != GLU_POINT) {
			needCache3 = GL_TRUE;
		}
		if (qobj->drawStyle == GLU_LINE) {
			needCache2 = GL_TRUE;
		}
	}

	for (i = 0; i < slices; i++) {
		angle = 2 * PI * i / slices;
		sinCache1a[i] = SIN(angle);
		cosCache1a[i] = COS(angle);
		if (needCache2) {
			sinCache2a[i] = sinCache1a[i];
			cosCache2a[i] = cosCache1a[i];
		}
	}

	for (j = 0; j <= stacks; j++) {
		angle = PI * j / stacks;
		if (needCache2) {
			if (qobj->orientation == GLU_OUTSIDE) {
				sinCache2b[j] = SIN(angle);
				cosCache2b[j] = COS(angle);
			} else {
				sinCache2b[j] = -SIN(angle);
				cosCache2b[j] = -COS(angle);
			}
		}
		sinCache1b[j] = radius * SIN(angle);
		cosCache1b[j] = radius * COS(angle);
	}

	sinCache1b[0] = 0;
	sinCache1b[stacks] = 0;

	if (needCache3) {
		for (i = 0; i < slices; i++) {
			angle = 2 * PI * (i-0.5) / slices;
			sinCache3a[i] = SIN(angle);
			cosCache3a[i] = COS(angle);
		}
		for (j = 0; j <= stacks; j++) {
			angle = PI * (j - 0.5) / stacks;
			if (qobj->orientation == GLU_OUTSIDE) {
				sinCache3b[j] = SIN(angle);
				cosCache3b[j] = COS(angle);
			} else {
				sinCache3b[j] = -SIN(angle);
				cosCache3b[j] = -COS(angle);
			}
		}
	}

	sinCache1a[slices] = sinCache1a[0];
	cosCache1a[slices] = cosCache1a[0];
	if (needCache2) {
		sinCache2a[slices] = sinCache2a[0];
		cosCache2a[slices] = cosCache2a[0];
	}
	if (needCache3) {
		sinCache3a[slices] = sinCache3a[0];
		cosCache3a[slices] = cosCache3a[0];
	}

	switch (qobj->drawStyle) {
	  case GLU_FILL:
		  if (!(qobj->textureCoords)) {
			  start = 1;
			  finish = stacks - 1;

			  sintemp2 = sinCache1b[1];
			  zHigh = cosCache1b[1];
			  switch(qobj->normals) {
	  case GLU_FLAT:
		  sintemp3 = sinCache3b[1];
		  costemp3 = cosCache3b[1];
		  break;
	  case GLU_SMOOTH:
		  sintemp3 = sinCache2b[1];
		  costemp3 = cosCache2b[1];
		  glNormal3f(sinCache2a[0] * sinCache2b[0],
			  cosCache2a[0] * sinCache2b[0],
			  cosCache2b[0]);
		  break;
	  default:
		  break;
			  }
			  glBegin(GL_TRIANGLE_FAN);
			  glVertex3f(0.0, 0.0, radius);
			  if (qobj->orientation == GLU_OUTSIDE) {
				  for (i = slices; i >= 0; i--) {
					  switch(qobj->normals) {
	  case GLU_SMOOTH:
		  glNormal3f(sinCache2a[i] * sintemp3,
			  cosCache2a[i] * sintemp3,
			  costemp3);
		  break;
	  case GLU_FLAT:
		  if (i != slices) {
			  glNormal3f(sinCache3a[i+1] * sintemp3,
				  cosCache3a[i+1] * sintemp3,
				  costemp3);
		  }
		  break;
	  case GLU_NONE:
	  default:
		  break;
					  }
					  glVertex3f(sintemp2 * sinCache1a[i],
						  sintemp2 * cosCache1a[i], zHigh);
				  }
			  } else {
				  for (i = 0; i <= slices; i++) {
					  switch(qobj->normals) {
	  case GLU_SMOOTH:
		  glNormal3f(sinCache2a[i] * sintemp3,
			  cosCache2a[i] * sintemp3,
			  costemp3);
		  break;
	  case GLU_FLAT:
		  glNormal3f(sinCache3a[i] * sintemp3,
			  cosCache3a[i] * sintemp3,
			  costemp3);
		  break;
	  case GLU_NONE:
	  default:
		  break;
					  }
					  glVertex3f(sintemp2 * sinCache1a[i],
						  sintemp2 * cosCache1a[i], zHigh);
				  }
			  }
			  glEnd();

			  sintemp2 = sinCache1b[stacks-1];
			  zHigh = cosCache1b[stacks-1];
			  switch(qobj->normals) {
	  case GLU_FLAT:
		  sintemp3 = sinCache3b[stacks];
		  costemp3 = cosCache3b[stacks];
		  break;
	  case GLU_SMOOTH:
		  sintemp3 = sinCache2b[stacks-1];
		  costemp3 = cosCache2b[stacks-1];
		  glNormal3f(sinCache2a[stacks] * sinCache2b[stacks],
			  cosCache2a[stacks] * sinCache2b[stacks],
			  cosCache2b[stacks]);
		  break;
	  default:
		  break;
			  }
			  glBegin(GL_TRIANGLE_FAN);
			  glVertex3f(0.0, 0.0, -radius);
			  if (qobj->orientation == GLU_OUTSIDE) {
				  for (i = 0; i <= slices; i++) {
					  switch(qobj->normals) {
	  case GLU_SMOOTH:
		  glNormal3f(sinCache2a[i] * sintemp3,
			  cosCache2a[i] * sintemp3,
			  costemp3);
		  break;
	  case GLU_FLAT:
		  glNormal3f(sinCache3a[i] * sintemp3,
			  cosCache3a[i] * sintemp3,
			  costemp3);
		  break;
	  case GLU_NONE:
	  default:
		  break;
					  }
					  glVertex3f(sintemp2 * sinCache1a[i],
						  sintemp2 * cosCache1a[i], zHigh);
				  }
			  } else {
				  for (i = slices; i >= 0; i--) {
					  switch(qobj->normals) {
	  case GLU_SMOOTH:
		  glNormal3f(sinCache2a[i] * sintemp3,
			  cosCache2a[i] * sintemp3,
			  costemp3);
		  break;
	  case GLU_FLAT:
		  if (i != slices) {
			  glNormal3f(sinCache3a[i+1] * sintemp3,
				  cosCache3a[i+1] * sintemp3,
				  costemp3);
		  }
		  break;
	  case GLU_NONE:
	  default:
		  break;
					  }
					  glVertex3f(sintemp2 * sinCache1a[i],
						  sintemp2 * cosCache1a[i], zHigh);
				  }
			  }
			  glEnd();
		  } else {
			  start = 0;
			  finish = stacks;
		  }
		  for (j = start; j < finish; j++) {
			  zLow = cosCache1b[j];
			  zHigh = cosCache1b[j+1];
			  sintemp1 = sinCache1b[j];
			  sintemp2 = sinCache1b[j+1];
			  switch(qobj->normals) {
	  case GLU_FLAT:
		  sintemp4 = sinCache3b[j+1];
		  costemp4 = cosCache3b[j+1];
		  break;
	  case GLU_SMOOTH:
		  if (qobj->orientation == GLU_OUTSIDE) {
			  sintemp3 = sinCache2b[j+1];
			  costemp3 = cosCache2b[j+1];
			  sintemp4 = sinCache2b[j];
			  costemp4 = cosCache2b[j];
		  } else {
			  sintemp3 = sinCache2b[j];
			  costemp3 = cosCache2b[j];
			  sintemp4 = sinCache2b[j+1];
			  costemp4 = cosCache2b[j+1];
		  }
		  break;
	  default:
		  break;
			  }

			  glBegin(GL_QUAD_STRIP);
			  for (i = 0; i <= slices; i++) {
				  switch(qobj->normals) {
	  case GLU_SMOOTH:
		  glNormal3f(sinCache2a[i] * sintemp3,
			  cosCache2a[i] * sintemp3,
			  costemp3);
		  break;
	  case GLU_FLAT:
	  case GLU_NONE:
	  default:
		  break;
				  }
				  if (qobj->orientation == GLU_OUTSIDE) {
					  if (qobj->textureCoords) {
						  glTexCoord2f(1 - (float) i / slices,
							  1 - (float) (j+1) / stacks);
					  }
					  glVertex3f(sintemp2 * sinCache1a[i],
						  sintemp2 * cosCache1a[i], zHigh);
				  } else {
					  if (qobj->textureCoords) {
						  glTexCoord2f(1 - (float) i / slices,
							  1 - (float) j / stacks);
					  }
					  glVertex3f(sintemp1 * sinCache1a[i],
						  sintemp1 * cosCache1a[i], zLow);
				  }
				  switch(qobj->normals) {
	  case GLU_SMOOTH:
		  glNormal3f(sinCache2a[i] * sintemp4,
			  cosCache2a[i] * sintemp4,
			  costemp4);
		  break;
	  case GLU_FLAT:
		  glNormal3f(sinCache3a[i] * sintemp4,
			  cosCache3a[i] * sintemp4,
			  costemp4);
		  break;
	  case GLU_NONE:
	  default:
		  break;
				  }
				  if (qobj->orientation == GLU_OUTSIDE) {
					  if (qobj->textureCoords) {
						  glTexCoord2f(1 - (float) i / slices,
							  1 - (float) j / stacks);
					  }
					  glVertex3f(sintemp1 * sinCache1a[i],
						  sintemp1 * cosCache1a[i], zLow);
				  } else {
					  if (qobj->textureCoords) {
						  glTexCoord2f(1 - (float) i / slices,
							  1 - (float) (j+1) / stacks);
					  }
					  glVertex3f(sintemp2 * sinCache1a[i],
						  sintemp2 * cosCache1a[i], zHigh);
				  }
			  }
			  glEnd();
		  }
		  break;
	  case GLU_POINT:
		  glBegin(GL_POINTS);
		  for (j = 0; j <= stacks; j++) {
			  sintemp1 = sinCache1b[j];
			  costemp1 = cosCache1b[j];
			  switch(qobj->normals) {
	  case GLU_FLAT:
	  case GLU_SMOOTH:
		  sintemp2 = sinCache2b[j];
		  costemp2 = cosCache2b[j];
		  break;
	  default:
		  break;
			  }
			  for (i = 0; i < slices; i++) {
				  switch(qobj->normals) {
	  case GLU_FLAT:
	  case GLU_SMOOTH:
		  glNormal3f(sinCache2a[i] * sintemp2,
			  cosCache2a[i] * sintemp2,
			  costemp2);
		  break;
	  case GLU_NONE:
	  default:
		  break;
				  }

				  zLow = j * radius / stacks;

				  if (qobj->textureCoords) {
					  glTexCoord2f(1 - (float) i / slices,
						  1 - (float) j / stacks);
				  }
				  glVertex3f(sintemp1 * sinCache1a[i],
					  sintemp1 * cosCache1a[i], costemp1);
			  }
		  }
		  glEnd();
		  break;
	  case GLU_LINE:
	  case GLU_SILHOUETTE:
		  for (j = 1; j < stacks; j++) {
			  sintemp1 = sinCache1b[j];
			  costemp1 = cosCache1b[j];
			  switch(qobj->normals) {
	  case GLU_FLAT:
	  case GLU_SMOOTH:
		  sintemp2 = sinCache2b[j];
		  costemp2 = cosCache2b[j];
		  break;
	  default:
		  break;
			  }

			  glBegin(GL_LINE_STRIP);
			  for (i = 0; i <= slices; i++) {
				  switch(qobj->normals) {
	  case GLU_FLAT:
		  glNormal3f(sinCache3a[i] * sintemp2,
			  cosCache3a[i] * sintemp2,
			  costemp2);
		  break;
	  case GLU_SMOOTH:
		  glNormal3f(sinCache2a[i] * sintemp2,
			  cosCache2a[i] * sintemp2,
			  costemp2);
		  break;
	  case GLU_NONE:
	  default:
		  break;
				  }
				  if (qobj->textureCoords) {
					  glTexCoord2f(1 - (float) i / slices,
						  1 - (float) j / stacks);
				  }
				  glVertex3f(sintemp1 * sinCache1a[i],
					  sintemp1 * cosCache1a[i], costemp1);
			  }
			  glEnd();
		  }
		  for (i = 0; i < slices; i++) {
			  sintemp1 = sinCache1a[i];
			  costemp1 = cosCache1a[i];
			  switch(qobj->normals) {
	  case GLU_FLAT:
	  case GLU_SMOOTH:
		  sintemp2 = sinCache2a[i];
		  costemp2 = cosCache2a[i];
		  break;
	  default:
		  break;
			  }

			  glBegin(GL_LINE_STRIP);
			  for (j = 0; j <= stacks; j++) {
				  switch(qobj->normals) {
	  case GLU_FLAT:
		  glNormal3f(sintemp2 * sinCache3b[j],
			  costemp2 * sinCache3b[j],
			  cosCache3b[j]);
		  break;
	  case GLU_SMOOTH:
		  glNormal3f(sintemp2 * sinCache2b[j],
			  costemp2 * sinCache2b[j],
			  cosCache2b[j]);
		  break;
	  case GLU_NONE:
	  default:
		  break;
				  }

				  if (qobj->textureCoords) {
					  glTexCoord2f(1 - (float) i / slices,
						  1 - (float) j / stacks);
				  }
				  glVertex3f(sintemp1 * sinCache1b[j],
					  costemp1 * sinCache1b[j], cosCache1b[j]);
			  }
			  glEnd();
		  }
		  break;
	  default:
		  break;
	}
}
*/
void COpenGLDriver::EndRender()
{
	CNullDriver::EndRender();

	IDrawableFaceManager *dem = SceneManager->GetDrawableFaceManager();

	u32 Size = dem->GetSize3DFaces();

	if (Size)
	{

        Apply3DView();

        u32 ILight(0);
        for (u32 i=0;i<dem->GetSizeLights();i++)
        {
            ApplyLight(dem->GetRenderizableLight(i),ILight);
            ILight++;
        }

//	    GLUquadric *GLUQmyQuad=gluNewQuadric();
//	    slices = stacks = resolution;
//	    gluSphere2( GLUQmyQuad ,0.14 ,40 ,40);

		if (UseVertexArray)
			glEnableClientState(GL_VERTEX_ARRAY);

		for (u32 i=0;i<Size;i++)
			if (UseVertexArray)
				DoRender3DVertexArray(dem->GetEntity3D(i));
			else
				DoRender3D(dem->GetEntity3D(i));

		if (UseVertexArray)
			glDisableClientState(GL_VERTEX_ARRAY);
	}

	Size = dem->GetSize2DFaces();

	if (Size)
	{
//		ClearBuffers(true,true,true,CColor(0.0,0.0,0.0));
		glDisable(GL_LIGHTING);
		Apply2DView();
//		glEnable(GL_ALPHA_TEST);
//		glAlphaFunc(GL_GREATER, 0.f);
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

		for (u32 i=0;i<Size;i++)
		{
			DoRender2D(dem->GetEntity2D(i));
		}
		glDisable(GL_BLEND);
		glEnable(GL_LIGHTING);
	}
}

void COpenGLDriver::DoRender3D(IDrawableFace *df)
{
	ITexture *Tex(df->GetTexture());
	vPos *Normal(df->GetNormal());
	vPos *TransformationMatrix(df->GetTransform());
	u32 NumVectors(df->GetNumVectors());

#ifdef HIGH_PRECCISSION_POSSITIONS
	glLoadMatrixd(TransformationMatrix);
#else
	glLoadMatrixf(TransformationMatrix);
#endif

	if (Tex)
		Tex->ActivateTexture();

	glBegin(GL_POLYGON);
	ApplyMaterial3D(df);

	glNormal3fv(Normal);

	for (u32 j=0;j<NumVectors;j++)
	{
//		vPos *Temp = df->GetVector(j);
		if (Tex)
#ifdef HIGH_PRECCISSION_POSSITIONS
			glTexCoord2dv(df->GetTexCoord(j));
		glNormal3dv(Normal);
		glVertex3dv(df->GetVector(j));
#else
			glTexCoord2fv(df->GetTexCoord(j));
		glNormal3fv(Normal);
		glVertex3fv(df->GetVector(j));
#endif
	}

	glEnd();

	if (Tex)
		Tex->DeActivateTexture();
}

void COpenGLDriver::DoRender3DVertexArray(IDrawableFace *df)
{
	ITexture *Tex(df->GetTexture());
	vPos *Normal(df->GetNormal());
	vPos *TransformationMatrix(df->GetTransform());
	u32 NumVectors(df->GetNumVectors());

#ifdef HIGH_PRECCISSION_POSSITIONS
	glLoadMatrixd(TransformationMatrix);
#else
	glLoadMatrixf(TransformationMatrix);
#endif
	glVertexPointer(3,
#ifdef HIGH_PRECCISSION_POSSITIONS
		GL_DOUBLE
#else
		GL_FLOAT
#endif
		,0,df->GetCompleteVectorClock());
	glDrawArrays(GL_POLYGON,0,NumVectors);
}

void COpenGLDriver::DoRender2D(IDrawableFace *df)
{
	ITexture *Tex(df->GetTexture());
	vPos *Normal(df->GetNormal());
	vPos *TransformationMatrix(df->GetTransform());
	u32 NumVectors(df->GetNumVectors());

//	glPushMatrix();
#ifdef HIGH_PRECCISSION_POSSITIONS
	glLoadMatrixd(TransformationMatrix);
#else
	glLoadMatrixf(TransformationMatrix);
#endif

	if (Tex)
		Tex->ActivateTexture();

	glBegin(GL_POLYGON);

	ApplyMaterial2D(df);

	for (u32 j=0;j<NumVectors;j++)
	{
		vPos *p = df->GetTexCoord(j);
		vPos *Temp = df->GetVector(j);

		if (Tex)
#ifdef HIGH_PRECCISSION_POSSITIONS
			glTexCoord2dv(df->GetTexCoord(j));
		glVertex3dv(df->GetVector(j));
#else
			glTexCoord2fv(df->GetTexCoord(j));
		glVertex3fv(df->GetVector(j));
#endif
	}

	glEnd();

	if (Tex)
		Tex->DeActivateTexture();

//	glPopMatrix();

}

void COpenGLDriver::ClearBuffers(bool backBuffer, bool zBuffer, bool stencilBuffer, CColor &color)
{
	GLbitfield mask = 0;
	if (backBuffer)
	{
		glClearColor((GLclampf)color.r,(GLclampf)color.g,(GLclampf)color.b,(GLclampf)color.a);
		mask |= GL_COLOR_BUFFER_BIT;
	}

	if (zBuffer)
	{
		glDepthMask(GL_TRUE);
		mask |= GL_DEPTH_BUFFER_BIT;
	}

	if (stencilBuffer)
		mask |= GL_STENCIL_BUFFER_BIT;

	glClear(mask);
}

void COpenGLDriver::ApplyMaterial3D(IMaterial *mat)
{
	memcpy(amb,mat->GetAmbientVector(),sizeof(f32)*4);
	memcpy(dif,mat->GetDifuseVector(),sizeof(f32)*4);
	memcpy(spec,mat->GetSpecularVector(),sizeof(f32)*4);
	glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,amb);
	glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,dif);
	glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,spec);
	glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,0.5);
}

void COpenGLDriver::ApplyMaterial2D(IMaterial *mat)
{
	CColor Ambient(mat->GetAmbient());
	f32 amb[4] = {(f32)Ambient.r,(f32)Ambient.g,(f32)Ambient.b,(f32)Ambient.a};
	glColor4fv(amb);
}

void COpenGLDriver::Apply3DCamera(I3DCameraSceneNode *cam)
{
	InitProjectionMatrix();
#ifdef HIGH_PRECCISSION_POSSITIONS
	glLoadMatrixd(cam->GetProjectionMatrix().m);
#else
	glLoadMatrixf(cam->GetProjectionMatrix().m);
#endif
	InitViewMatrix();
}

void COpenGLDriver::Apply2DCamera(I2DCameraSceneNode *cam)
{
	InitProjectionMatrix();
#ifdef HIGH_PRECCISSION_POSSITIONS
//	glLoadMatrixd(cam->GetProjectionMatrix().m);
#else
//	glLoadMatrixf(cam->GetProjectionMatrix().m);
#endif
	InitViewMatrix();
//	glOrtho(-2.0,2.0,-2.0,2.0,0.1,10.0);
}

void COpenGLDriver::ApplyLight(IRenderizableLight *Light,u32 IndexLight)
{
	u32 l = GL_LIGHT0+IndexLight;

	vPos *amb = Light->GetAmbientVector();
	vPos *dif = Light->GetDifuseVector();
	vPos *spec = Light->GetSpecularVector();
	glLightf(l,GL_SPOT_CUTOFF,Light->CutOff);
	glLightfv(l,GL_SPOT_DIRECTION,Light->Direction);
//	glLightfv(l,GL_AMBIENT,amb);
//	glLightfv(l,GL_DIFFUSE,dif);
//	glLightfv(l,GL_SPECULAR,spec);
	Light->Position[3] = 1.0;
	glLightfv(l,GL_POSITION,Light->Position);
	glEnable(l);
}

void COpenGLDriver::Apply3DView()
{
	I3DCameraSceneNode *ac = SceneManager->GetActive3DCamera();

	if (ac)
	{
		ac->OnRender();
		Apply3DCamera(ac);
	}
}

void COpenGLDriver::Apply2DView()
{
	I2DCameraSceneNode *ac = SceneManager->GetActive2DCamera();

	if (ac)
	{
		ac->OnRender();
		Apply2DCamera(ac);
	}
}

void COpenGLDriver::InitProjectionMatrix()
{
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
}

void COpenGLDriver::InitViewMatrix()
{
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

vector2dvpos COpenGLDriver::GetPositionIn2D(const vector2dvpos &Position)
{
	return vector2dvpos(GetPositionIn2DX(Position.X),GetPositionIn2DY(Position.Y));
}

vPos COpenGLDriver::GetPositionIn2DX(vPos PosX)
{
	return (vPos)(-1.0 + (PosX / 2.0));
}

vPos COpenGLDriver::GetPositionIn2DY(vPos PosY)
{
	return (vPos)(-1.0 + (PosY / 2.0));
}
